package dryven.reflection;

import java.io.IOException;
import java.io.InputStream;

import org.objectweb.asm.ClassReader;

import dryven.discovery.ClassDataScanner;
import dryven.discovery.ClassDiscoveryAdapter;
import dryven.reflection.classlocator.ClassLoaderLocator;
import dryven.reflection.classlocator.ClassLocator;

public class MethodIterator {
	
	private MethodListener _listener;
	private InputStream _inputstream;
	
	public MethodIterator(MethodListener listener, TypeRef t) {
		this(listener,t,new ClassLoaderLocator());
	}
	
	public MethodIterator(MethodListener listener, TypeRef t, ClassLocator classLocator) {
		_listener = listener;
		_inputstream = classLocator.getTypeAsInputStream(t);
	}
	
	public MethodIterator(MethodListener listener, InputStream byteCode) {
		_listener = listener;
		_inputstream = byteCode;
	}
	
	public void iterate() {
		try {
			ClassDataScanner scanner = new ClassDataScanner(new Listener());
			ClassReader reader = new ClassReader(_inputstream);
			reader.accept(scanner, ClassReader.SKIP_CODE | ClassReader.SKIP_DEBUG);
			_inputstream.close();
		} catch(IOException e) {
			throw new RuntimeException("Error while reading class file", e);
		}
	}
	
	class Listener extends ClassDiscoveryAdapter {

		private TypeRef _currentType;
		
		@Override
		public void onClass(String typeName, String superClassName,
				String[] interfaces) {
			_currentType = new LiteralTypeRef(typeName);
		}

		@Override
		public boolean onMethod(int access, String typeName, String methodName,
				TypeRef[] types, TypeRef returnType) {
			_listener.methodFound(new Method(methodName, _currentType, returnType, types, access));
			return false;
		}
		
	}
}

